package exam2013;

/**
 * Permutations generator
 * @param <T> Elements type
 */
public class P2Q2<T> {
	
	/**
	 * Array
	 */
	private T[] arr;
	
	/**
	 * Callback
	 */
	private Callback<T> cb;
	
	
	/**
	 * Creates a permutations generator
	 * @param arr Array
	 * @param cb Callback
	 */
	public P2Q2(T[] arr, Callback<T> cb) {
		this.arr = arr;
		this.cb = cb;
	}
	
	/**
	 * Generates permutations of the given array
	 */
	public void permutations() {
		permutations(0);
	}
		
	/**
	 * Generates permutations of the given array
	 * @param i Count of locked cells
	 */
	private void permutations(int i) {
		if (i == arr.length-1)
			cb.update(arr);
		else {
			int r = arr.length-i; //rounds
			while (r-- != 0) {
				//ROL operation
				T e = arr[i]; //leftmost character (otherwise erased)
				for (int j = i+1; j<arr.length; j++)
					arr[j-1] = arr[j]; //shift left
				arr[arr.length-1] = e; //restore
				//recursive call
				permutations(i+1);
			}
		}
	}
	
	
	/**
	 * Callback
	 * @param <T> Elements type
	 */
	public interface Callback<T> {
		public void update(T[] arr);
	}
	
	
	/**
	 * Generates permutations of the given sequence:
	 * <ul>
	 * <li>If there's only one argument, generates "anagrams" of the string</li>
	 * <li>If there are more arguments, generates all permutations of the given strings</li>
	 * </ul>
	 * @param args
	 */
	public static void main(String[] args) {
		if (args.length == 1) {
			Character[] ch = new Character[args[0].length()];
			for (int i=0; i<args[0].length(); i++)
				ch[i] = args[0].charAt(i);
			new P2Q2<Character>(ch, new Callback<Character>() {
				@Override
				public void update(Character[] arr) {
					for (Character c: arr)
						System.out.print(c.toString());
					System.out.print('\n');
				}
			}).permutations();
		}
		else {
			new P2Q2<String>(args, new Callback<String>() {
				@Override
				public void update(String[] arr) {
					StringBuilder sb = new StringBuilder("[");
					for (String s: arr) {
						sb.append(s);
						sb.append(',');
					}
					sb.setCharAt(sb.length()-1, ']');
					System.out.println(sb.toString());
				}
			}).permutations();
		}
	}

}
